package com.xli.mis.codemain.service.impl;

import cn.hutool.extra.spring.SpringUtil;
import com.alicp.jetcache.Cache;
import com.alicp.jetcache.CacheManager;
import com.alicp.jetcache.anno.CacheConsts;
import com.alicp.jetcache.anno.CacheType;
import com.alicp.jetcache.template.QuickConfig;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xli.mis.codeitems.service.ICodeItemsService;
import com.xli.mis.codemain.entity.CodeMain;
import com.xli.mis.codemain.entity.CodeMainCache;
import com.xli.mis.codemain.mapper.CodeMainMapper;
import com.xli.mis.codemain.mapper.ICodeMainCacheMapper;
import com.xli.mis.codemain.service.ICodeMainService;
import jakarta.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import java.time.Duration;
import java.util.List;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

@Validated
@Service
public class CodeMainServiceImpl extends ServiceImpl<CodeMainMapper, CodeMain> implements ICodeMainService {

    private final Lock lock = new ReentrantLock();

    @Autowired
    CacheManager cacheManager;

    Cache<String, CodeMainCache> codeMainCache;

    @PostConstruct
    public void init() {
        lock.lock();
        try {
            QuickConfig qc = QuickConfig.newBuilder("code_main:entity:")
                    .expire(Duration.ofSeconds(CacheConsts.DEFAULT_EXPIRE))
                    .cacheType(CacheType.BOTH)
                    .syncLocal(true)
                    .build();
            codeMainCache = cacheManager.getOrCreateCache(qc);

            List<CodeMain> codeMainList = this.findList(new QueryWrapper<>());
            List<CodeMainCache> cacheList = ICodeMainCacheMapper.INSTANCE.toCacheList(codeMainList);

            cacheList.forEach(cache -> codeMainCache.put(cache.getCode_name(), cache));
        } finally {
            lock.unlock();
        }
    }

    @Override
    public boolean insert(CodeMain codeMain) {
        lock.lock();
        try {
            boolean result = this.save(codeMain);
            if (result) {
                codeMainCache.put(codeMain.getCode_name(), ICodeMainCacheMapper.INSTANCE.toCacheEntity(codeMain));
            }
            return result;
        } finally {
            lock.unlock();
        }
    }

    @Override
    public boolean delete(Long id) {
        lock.lock();
        ICodeItemsService iCodeItemsService = SpringUtil.getBean(ICodeItemsService.class);
        try {
            CodeMain codeMain = this.find(id);
            if (codeMain != null) {
                boolean result = this.removeById(id);
                if (result) {
                    codeMainCache.remove(codeMain.getCode_name());
                    iCodeItemsService.deleteByCodeId(id);
                }
                return result;
            }
            return false;
        } finally {
            lock.unlock();
        }
    }

    @Override
    public boolean update(CodeMain codeMain) {
        lock.lock();
        try {
            CodeMain main = this.find(codeMain.getId());
            if (main != null) {
                boolean result = this.updateById(codeMain);
                if (result) {
                    codeMainCache.remove(main.getCode_name());
                    codeMainCache.put(main.getCode_name(), ICodeMainCacheMapper.INSTANCE.toCacheEntity(codeMain));
                }
                return result;
            }
            return false;
        } finally {
            lock.unlock();
        }
    }

    @Override
    public CodeMain find(Long id) {
        return this.getById(id);
    }

    @Override
    public List<CodeMain> findList(QueryWrapper<CodeMain> qw) {
        return this.list(qw);
    }

    @Override
    public Page<CodeMain> findList(QueryWrapper<CodeMain> qw, long current, long size) {
        return this.page(new Page<>(current, size), qw);
    }

    @Override
    public CodeMain findCodeMainByName(String name) {
        CodeMainCache cache = codeMainCache.get(name);
        if (cache != null) {
            return ICodeMainCacheMapper.INSTANCE.toEntity(cache);
        }
        return null;
    }

    @Override
    public Long getCodeIdByName(String name) {
        CodeMain codeMain = this.findCodeMainByName(name);
        if (codeMain != null) {
            return codeMain.getId();
        }
        return null;
    }
}
